---
title: Streaming
description: Stream agent output in real time using the Runner
---

import { Code } from '@astrojs/starlight/components';
import basicStreamingExample from '../../../../../examples/docs/streaming/basicStreaming.ts?raw';
import nodeTextStreamExample from '../../../../../examples/docs/streaming/nodeTextStream.ts?raw';
import handleAllEventsExample from '../../../../../examples/docs/streaming/handleAllEvents.ts?raw';
import streamedHITLExample from '../../../../../examples/docs/streaming/streamedHITL.ts?raw';

The Agents SDK can deliver output from the model and other execution
steps incrementally. Streaming keeps your UI responsive and avoids
waiting for the entire final result before updating the user.

## Enabling streaming

Pass a `{ stream: true }` option to `Runner.run()` to obtain a streaming
object rather than a full result:

<Code
  lang="typescript"
  code={basicStreamingExample}
  title="Enabling streaming"
/>

When streaming is enabled the returned `stream` implements the
`AsyncIterable` interface. Each yielded event is an object describing
what happened within the run. The stream yields one of three event types, each describing a different part of the agent's execution.
Most applications only want the model's
text though, so the stream provides helpers.

### Get the text output

Call `stream.toTextStream()` to obtain a stream of the emitted text.
When `compatibleWithNodeStreams` is `true` the return value is a regular
Node.js `Readable`. We can pipe it directly into `process.stdout` or
another destination.

<Code
  lang="typescript"
  code={nodeTextStreamExample}
  title="Logging out the text as it arrives"
  meta={`{13-17}`}
/>

The promise `stream.completed` resolves once the run and all pending
callbacks are completed. Always await it if you want to ensure there is
no more output.

### Listen to all events

You can use a `for await` loop to inspect each event as it arrives.
Useful information includes low level model events, any agent switches
and SDK specific run information:

<Code
  lang="typescript"
  code={handleAllEventsExample}
  title="Listening to all events"
/>

See [the streamed example](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns/streamed.ts)
for a fully worked script that prints both the plain text stream and the
raw event stream.

## Event types

The stream yields three different event types:

### raw_model_stream_event

```ts
type RunRawModelStreamEvent = {
  type: 'raw_model_stream_event';
  data: ResponseStreamEvent;
};
```

Example:

```json
{
  "type": "raw_model_stream_event",
  "data": {
    "type": "output_text_delta",
    "delta": "Hello"
  }
}
```

### run_item_stream_event

```ts
type RunItemStreamEvent = {
  type: 'run_item_stream_event';
  name: RunItemStreamEventName;
  item: RunItem;
};
```

Example handoff payload:

```json
{
  "type": "run_item_stream_event",
  "name": "handoff_occurred",
  "item": {
    "type": "handoff_call",
    "id": "h1",
    "status": "completed",
    "name": "transfer_to_refund_agent"
  }
}
```

### agent_updated_stream_event

```ts
type RunAgentUpdatedStreamEvent = {
  type: 'agent_updated_stream_event';
  agent: Agent<any, any>;
};
```

Example:

```json
{
  "type": "agent_updated_stream_event",
  "agent": {
    "name": "Refund Agent"
  }
}
```

## Human in the loop while streaming

Streaming is compatible with handoffs that pause execution (for example
when a tool requires approval). The `interruption` field on the stream
object exposes the interruptions, and you can continue execution by
calling `state.approve()` or `state.reject()` for each of them.
Executing again with `{ stream: true }` resumes streaming output.

<Code
  lang="typescript"
  code={streamedHITLExample}
  title="Handling human approval while streaming"
/>

A fuller example that interacts with the user is
[`human-in-the-loop-stream.ts`](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns/human-in-the-loop-stream.ts).

## Tips

- Remember to wait for `stream.completed` before exiting to ensure all
  output has been flushed.
- The initial `{ stream: true }` option only applies to the call where it
  is provided. If you re-run with a `RunState` you must specify the
  option again.
- If your application only cares about the textual result prefer
  `toTextStream()` to avoid dealing with individual event objects.

With streaming and the event system you can integrate an agent into a
chat interface, terminal application or any place where users benefit
from incremental updates.
